import os
import re
import sys
import time
import traceback
from datetime import datetime

import logzero
from logzero import logger
from tqdm import tqdm
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException

from config import REPORT_ERROR_COLLECTION_NAME, SCREENSHOT_PATH
from utils import open_driver, track_alert, get_mongo_collection, record_run_status

COLLECTION_LIST = 'bcy_cos_list'
COLLECTION_DETAIL = 'bcy_cos_detail'
COLLECTION_FEED = 'bcy_cos_detail_feed'
# COLLECTION_FEED = 'report_error'
current_module = os.path.splitext(os.path.basename(__file__))[0]
logzero.logfile(f"/tmp/{current_module}.log", maxBytes=30_000_000, backupCount=3, encoding='utf-8')
RE_NUM = re.compile(r'\d+')
db_feed = get_mongo_collection(COLLECTION_FEED)
db = get_mongo_collection(COLLECTION_DETAIL)
db_list = get_mongo_collection(COLLECTION_LIST)
error_db = get_mongo_collection(REPORT_ERROR_COLLECTION_NAME)

insert_count = 0


@record_run_status(current_module)
def spider(from_href):
    cos_list = db_feed.find(no_cursor_timeout=True)
    if from_href:
        need_skip = True
    else:
        need_skip = False
    is_skiped = False
    with open_driver() as driver:
        with track_alert(driver):
            for cos in tqdm(cos_list):
                logger.debug('*' * 50)
                href = cos['href']
                try:
                    if need_skip and not is_skiped:
                        if from_href == href:
                            is_skiped = True
                            logger.info(f'从{from_href}开始')
                        else:
                            logger.debug(f'跳过{href}')
                            continue
                    data = handle_detail(driver, href)
                    store_data(data, href)
                except (NoSuchElementException, StaleElementReferenceException) as e:
                    handle_exception(driver, e, href)
                else:
                    delete_error(href)
            cos_list.close()
            logger.info('完成')
            return insert_count


def handle_detail(driver, href):
    data = {'href': href, 'post_type': '', 'tags': [], 'p_num': '', 'post_time': None,
            'update_time': datetime.now()}
    driver.get(href)
    logger.info(f'访问 {href}')
    time.sleep(3)
    post_type = driver.find_element_by_css_selector('div.post__type>div.post__type_l>a').text
    p_num = driver.find_element_by_css_selector(
        'div.post__type>div.post__type_l>span:nth-child(2)').text
    post_time = driver.find_element_by_css_selector(
        'div.post__type>div.post__type_l>span:nth-child(3)').text
    data['post_type'] = post_type
    data['p_num'] = int(RE_NUM.search(p_num).group(0))
    data['post_time'] = post_time
    tags_ele = driver.find_elements_by_css_selector('ul.js-tags>li.js-delete-tag')
    for tag_ele in tags_ele:
        tag_id = tag_ele.get_attribute('data-tag-id')
        tag_name = tag_ele.get_attribute('data-tag-name')
        data['tags'].append({'tag_id': tag_id, 'tag_name': tag_name})
    return data


def store_data(data, href):
    global insert_count
    old_record = db.find_one({'href': href})
    if old_record:
        logger.info(f'{href} 已经存储，现在更新')
        db.update(old_record, {'$set': data})
    else:
        logger.info(f'{href}不存在，现在插入')
        logger.info(data)
        db.insert_one(data)
        insert_count += 1


def handle_exception(driver, e, href):
    no_right_text = driver.find_elements_by_css_selector('span.l-detail-no-right-to-see__text')
    break_law_text = driver.find_elements_by_css_selector('article > div > p > span')
    if no_right_text or break_law_text:
        db_list.remove({'href': href})
        logger.error('无法访问')
        delete_error(href)
        return
    if driver.current_url != href:
        db_list.remove({'href': href})
        logger.error('该页面不存在')
        delete_error(href)
        return
    driver.get_screenshot_as_file(
        f"{SCREENSHOT_PATH}/{COLLECTION_DETAIL}_{datetime.now().strftime('%Y-%m-%d %H %M %S')}.png")
    logger.error(e)
    logger.error(traceback.format_exc())
    error_record_condition = {'desp': COLLECTION_DETAIL, 'href': href}
    error_record = error_db.find_one(error_record_condition)
    if not error_record:
        error_db.insert_one(
            {'desp': COLLECTION_DETAIL, 'href': href, 'e': e,
             'e_traceback': traceback.format_exc(), 'update_time': datetime.now()})


def delete_error(href):
    db_feed.remove({'href': href})
    error_record_condition = {'desp': COLLECTION_DETAIL, 'href': href}
    error_record = error_db.find_one(error_record_condition)
    if error_record:
        error_db.delete_one(error_record_condition)
        logger.info('删掉异常记录')


if __name__ == '__main__':
    """
    第一个参数表示从哪个href开始爬，不传递直接从头爬
    """
    from_href = sys.argv[1] if len(sys.argv) == 2 else None
    spider(from_href)
